package v1

import (
	v1 "gitee.com/youkelike/ziam/zapi/apiserver/v1"
	"gitee.com/youkelike/ziam/zsdk2/rest"
	"gitee.com/youkelike/ziam/zutils/runtime"
)

type APIV1Interface interface {
	Secrets() SecretInterface
	Users() UserInterface
	Policies() PolicyInterface

	// 下面这样直接内嵌子接口不好，子接口之间可能出现方法同名冲突
	// SecretsGetter
	// UsersGetter
	// PoliciesGetter
}

// 只有 restclient 的构造方法会返回错误，所以要先实例化后存到字段，
type APIV1Client struct {
	restClient rest.Interface
}

// Users create and return user rest client.
func (c *APIV1Client) Users() UserInterface {
	// 不会返回错误的子构造方法，不需要在自己的构造方法中调用并用字段来事先存储，
	return newUsers(c.restClient)
}

// Secrets create and return secret rest client.
func (c *APIV1Client) Secrets() SecretInterface {
	return newSecrets(c.restClient)
}

// Policies create and return policy rest client.
func (c *APIV1Client) Policies() PolicyInterface {
	return newPolicies(c.restClient)
}

func NewForConfig(c *rest.Config) (*APIV1Client, error) {
	// 跟跟服务相关的默认配置
	SetConfigDefaults(c)

	// restclient 的构造方法会返回错误，所以要先实例化后存到字段，
	restClient, err := rest.RESTClientFor(c)
	if err != nil {
		return nil, err
	}

	return &APIV1Client{restClient}, nil
}

func NewForConfigOrDie(c *rest.Config) *APIV1Client {
	client, err := NewForConfig(c)
	if err != nil {
		panic(err)
	}

	return client
}

func New(c rest.Interface) *APIV1Client {
	return &APIV1Client{c}
}

func SetConfigDefaults(c *rest.Config) {
	// 对配置文件中的部分选项进行个性化设置
	if c.GroupVersion == nil {
		gv := v1.SchemeGroupVersion
		c.GroupVersion = &gv
	}

	c.APIPath = ""
	c.Negotiator = runtime.NewSimpleClientNegotiator()

	if c.UserAgent == "" {
		c.UserAgent = rest.DefaultUserAgent()
	}
}
